package com.jdaoyun.util;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import com.jdaoyun.a_empcsApi.entity.PushMessageLog;
import com.jdaoyun.a_empcsApi.service.PushMessageLogService;
import com.jdaoyun.result.R;
import com.jdaoyun.config.Head;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;


@Component
@Slf4j
public class DataSender {


    @Autowired
    private PushMessageLogService pushMeg;

    public R<JSONObject> sendData(Integer type, Integer size, String jsonBody, Integer tenantId) throws Exception {

        //1. 获取请求头参数
        Long nonce = IdUtil.getSnowflake(1, 1).nextId();//nonce随机值(格式不限，保证唯一就行)
        Long timestamp = System.currentTimeMillis(); //timestamp时间戳
        String signature = generateSignature(String.format("%s|%s", timestamp, nonce), Head.SECRETACCESSKEY);  //signature签名

        //2. 组装请求头
        JSONObject head = new JSONObject();
        head.set("accesskey", Head.ACCESSKEY);
        head.set("signature", signature);
        head.set("timestamp", String.valueOf(timestamp));
        head.set("nonce", String.valueOf(nonce));
        head.set("type", String.valueOf(type));
        head.set("size", String.valueOf(size));
        log.info(" 请求头：{}", head);

        //3. 加密请求体
        String encryptedData = encrypt(jsonBody, Head.SECRETACCESSKEY);
        JSONObject entries = new JSONObject();
        entries.set("encryptedData", encryptedData);
        log.info(" 请求体：{}", entries);


        //4. 发送请求
        return this.post(head, Head.BASE_URL, entries, jsonBody, type, tenantId);
    }


    public String generateSignature(String dataToSign, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException {
        Mac hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(
                Base64.getDecoder().decode(secretKey), "HmacSHA256");
        hmac.init(secretKeySpec);
        byte[] signature = hmac.doFinal(dataToSign.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(signature);
    }


    public String encrypt(String data, String secretKey) throws Exception {
        Key key = new
                SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * POST请求调用方式
     */
    public R<JSONObject> post(JSONObject head, String url, JSONObject requestBody, String jsonBody, Integer type, Integer tenantId) throws RestClientException {

        R<JSONObject> r = R.fail("发送post请求异常");
        try {
            String result = HttpRequest.post(url)
                    .body(requestBody.toString())
                    .header("accesskey", head.getStr("accesskey"))
                    .header("signature", head.getStr("signature"))
                    .header("timestamp", head.getStr("timestamp"))
                    .header("nonce", head.getStr("nonce"))
                    .header("type", head.getStr("type"))
                    .header("size", head.getStr("size"))
                    .execute().body();
            log.info(" 响应：{}", result);
            JSONObject entries = new JSONObject(result);
            PushMessageLog megLog = PushMessageLog.builder()
                    .targetUrl(url)//请求地址
                    .requestContent(requestBody.toString())//加密后请求体
                    .requestHead(head.toString())//请求头
                    .responseContent(result)//响应内容
                    .responseCode(entries.getInt("code"))//响应Code
                    .requestBody(jsonBody)//加密前请求体
                    .type(type)//区分类型
                    .tenantId(tenantId)//租户ID
                    .scheduledTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))
                    .pushTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))
                    .build();

            switch (type) {
                case 1:
                    megLog.setMethod("推送机构信息,PushCode.orgInfo");
                    break;
                case 2:
                    megLog.setMethod("推送车辆信息,PushCode.carInfo");
                    break;
                case 3:
                    megLog.setMethod("推送司机信息信息,PushCode.driverInfo");
                    break;
                case 4:
                    megLog.setMethod("推送医生护士信息,PushCode.doctorInfo");
                    break;
                case 5:
                    megLog.setMethod("推送接警信息,PushCode.rescueRecordAgencyTime");
                    break;
                case 6:
                    megLog.setMethod("推送各机构急救时间点信息,PushCode.emergencyAgencyTime");
                    break;
                case 7:
                    megLog.setMethod("推送任务各用时情况信息,PushCode.emergencyRecordTaskTime");
                    break;
                case 8:
                    megLog.setMethod("推送各任务诊断情况信息,PushCode.emergencyRecordTaskDiagnosis");
                    break;
                case 9:
                    megLog.setMethod("推送车辆实时位置信息,PushCode.vehicleRealTimeLocation");
                    break;
            }

            if (entries.getInt("code") == 0) {
                megLog.setStatus("成功");
                megLog.setResponseData(entries.getStr("data"));
                pushMeg.save(megLog);
                return R.ok(entries);
            }

            megLog.setStatus("失败");
            megLog.setErrorMessage(entries.getStr("message"));
            pushMeg.save(megLog);

            return R.fail(entries.getStr("message"));
        } catch (HttpException e) {
            log.error("异常：{}", e);
        }

        return r;
    }

}


